--- 'Monoid' wrappers for numeric data
module frege.data.wrapper.Num where

import Data.Monoid

{--
    'Monoid' wrapper for numbers with operation '*' and identity 1
-}
newtype Product a = Product { unwrap :: a } --- wrap a number
derive Show (Product a)
derive Eq   (Product a)
derive Ord  (Product a)

--- Haskell compatibility: get the value wrapped by 'Product'
getProduct = Product.unwrap


--- The 'Semigroup' instance for 'Product' uses operation '*'
instance Num a => Semigroup (Product a) where
    --- > Product 3 <> Product 7 == Product 21@
    Product x `mappend` Product y = Product (x * y)

--- The 'Monoid' instance for 'Product' has identity @1@
instance Num a => Monoid (Product a) where
    --- > Product 1@
    mempty = Product one

    
{--
    'Monoid' wrapper for numbers with operation '+' and identity 0
-}   
newtype Sum a = Sum { unwrap :: a }    --- wrap a number
derive Show (Sum a)
derive Eq   (Sum a)
derive Ord  (Sum a)

--- Haskell compatibility: get the value wrapped by 'Sum'
getSum = Sum.unwrap


--- The 'Semigroup' instance for 'Sum' uses operation '+'
instance Num a => Semigroup (Sum a) where
    --- > Sum 19 <> Sum 23 == Sum 42
    Sum x `mappend` Sum y = Sum (x + y)
  
--- The 'Monoid' instance for 'Sum' has identity @0@
instance Num a => Monoid (Sum a) where
    --- > Sum 0
    mempty = Sum zero


